package es.uclm.itsue.library;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import org.json.JSONObject;

import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.ToggleButton;

public class ItsueLibraryActivity extends Activity implements OnClickListener {
	


	public static String SERVERIP;
	public static final int SERVERPORT = 8080;
	
	private ServerTask st;
	private ServerSocket serverSocket;
	private Socket clientSocket;
	
    private ToggleButton serverTB;
	private TextView serverStatusTV;
    private TextView resultsTV;
    
    private SQLiteDatabase db;

   	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.server);
		
        serverTB = (ToggleButton) findViewById(R.id.server_ToggleButton);
        serverTB.setOnClickListener(this);

        resultsTV = (TextView) findViewById(R.id.results_TextView);        
		serverStatusTV = (TextView) findViewById(R.id.serverStatus_TextView);

		SERVERIP = getLocalIpAddress();
		Log.i("Server", "Server configured at " + SERVERIP + ":" + SERVERPORT);
		serverStatusTV.setText("Server configured at " + SERVERIP + ":" + SERVERPORT);
		
        LibrarySQLiteHelper bibHelper = new LibrarySQLiteHelper(this, "library.s3db", null, 2);
        db = bibHelper.getReadableDatabase();
	}

	@Override
	protected void onStop() {
		super.onStop();

		if(st == null) return;
		Log.i("Server", "Cancelando la tarea del servidor...");
		if(st.cancel(true))
			Log.i("Server", "Servidor detenido.");
		else
			Log.i("Server", "El servidor no pudo ser detenido.");
		
        db.close();

	}
	
    @Override
   	public void onClick(View v) {
   		switch (v.getId()) {
   		case R.id.server_ToggleButton:
   			if (serverTB.isChecked()) {
   	   			Log.i("Server", "Running server...");
   	        	st = new ServerTask();
   	        	st.execute();
   			}
   			else {
   	   			Log.i("Server", "Stopping server task..");
   				st.cancel(true);
   			}
   			break;
   		}
   	}
    
	public class ServerTask extends AsyncTask <Void, Integer, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			try {
				serverSocket = new ServerSocket(SERVERPORT);
			} 
			catch (IOException e) {
				Log.i("Server", "Problem creating server socket.");
				return null;
			}
			while (true) 
			{
				Log.i("Server", "Waiting clients...");
				try { 
					clientSocket = serverSocket.accept();					
					if(isCancelled()) return null;
				}
				catch (Exception e) {
					Log.e("Server", "Error in server socket: " + e.getMessage());
					return null;
				}
				Log.i("Server", "Client connected.");
				
				try {
					
					BufferedReader in = new BufferedReader(
							new InputStreamReader(clientSocket.getInputStream()),1024);
					String inTxt = in.readLine();
					if(isCancelled()) return null;

					Log.i("Server", "Input: " + inTxt);

					PrintWriter out = new PrintWriter(
    						new BufferedWriter(new OutputStreamWriter(clientSocket
    							.getOutputStream())), true);

		            JSONObject inJson = new JSONObject(inTxt);
		            String command = inJson.getString("command");
					
		            if( command.equals("getBooks"))
		            {
				        String option = inJson.getString("option");

				        if( option.equals("all"))
			            {
				            out.println("[");
				            Cursor c = db.rawQuery(" SELECT * FROM libros ", null);
				            publishProgress(c.getCount());
				            while (c.moveToNext()) {
			            		out.println("{\nid:'"  + c.getString(0) + "',");
			            		out.println("title:'"  + c.getString(1) + "',");
			            		out.println("author:'" + c.getString(2) + "'}");
			            		if(!c.isLast()) out.println(",");
				            } 
				            c.close();				            
				            out.println("]");
			            }

			            if( option.equals("available"))
			            {
				            out.println("[");
				            Cursor c = db.rawQuery(" SELECT * FROM libros WHERE lector=0 ", null);
				            publishProgress(c.getCount());
				            while (c.moveToNext()) {
			            		out.println("{\nid:'"  + c.getString(0) + "',");
			            		out.println("title:'"  + c.getString(1) + "',");
			            		out.println("author:'" + c.getString(2) + "'}");
			            		if(!c.isLast()) out.println(",");
				            } 
				            c.close();				            
				            out.println("]");
				            /*		            	
				            publishProgress(4);
					        String outTxt = "[ { id:'1', title: 'book number 1', author: 'author number 1' }," +
					        		          "{ id:'2', title: 'book number 2', author: 'author number 2' }," +
					           		          "{ id:'3', title: 'book number 3', author: 'author number 3' }," +
					        		          "{ id:'4', title: 'book number 4', author: 'author number 4' }]";
					        Log.i("Server", "Response: " + outTxt);
				            out.println(outTxt);
				            */				            
			            }

		            }

					clientSocket.close();
				} 
				catch (Exception e) {
					Log.e("Server", "Connection interrupted.");
					return null;
				}
				Log.i("Server", "Connection finished.");
			} 
		}
		
		

		@Override
		protected void onProgressUpdate(Integer... rows) {     
			resultsTV.setText(Integer.toString(rows[0]));
		}
		
		@Override
		protected void onCancelled() {
			Log.i("Server", "Stopping server socket...");
			try {
				serverSocket.close();
			} 
			catch (IOException e) {
				Log.e("Server", "Error stopping server socket.");
			}
			catch (NullPointerException e) {
				Log.e("Server", "Server socket not found.");
			}
			Log.i("Server", "Server socket stopped.");
		}
	}

	private String getLocalIpAddress() {
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); }
				}
			}
		} catch (SocketException e) {
			Log.e("Server", e.toString());
		}
		return null;
	}

}
